// ===================================
// 19.7.1 类型分类（Type Classification）
// ===================================
// 类型分类特征允许我们区分不同种类的类型，例如判断一个类型是否为指针、引用或函数等。

// 1.基本实现方式
// 主模板（默认情况）
template<typename T>
struct IsPointer : std::false_type {};

// 特化版本（针对指针类型）
template<typename T>
struct IsPointer<T*> : std::true_type {};
这种实现利用了模板特化的匹配规则，当T是指针类型时，特化版本会被选中。

// 2.处理CV限定符
对于带有const/volatile限定符的类型，需要额外的特化：

// 处理const指针
template<typename T>
struct IsPointer<T* const> : std::true_type {};

// 处理volatile指针
template<typename T>
struct IsPointer<T* volatile> : std::true_type {};

// 处理const volatile指针
template<typename T>
struct IsPointer<T* const volatile> : std::true_type {};

// ==================================
// 19.7.2 策略特征（Policy Traits）
// ==================================
策略特征不是用来检测类型特性，而是用来定义类型应该如何被处理。它们允许用户自定义行为。

// 1.示例：元素访问策略
// 默认策略
template<typename T>
struct ElementAccess {
    using ResultType = typename T::value_type;
    
    static ResultType& access(T& container, std::size_t idx) {
        return container[idx];
    }
};

// 针对指针类型的特化
template<typename T>
struct ElementAccess<T*> {
    using ResultType = T;
    
    static ResultType& access(T* array, std::size_t idx) {
        return array[idx];
    }
};

// 2.使用策略特征
template<typename Container>
void processElements(Container& c, std::size_t count) {
    using AccessPolicy = ElementAccess<Container>;
    using ElementType = typename AccessPolicy::ResultType;
    
    for (std::size_t i = 0; i < count; ++i) {
        ElementType& element = AccessPolicy::access(c, i);
        // 处理元素...
    }
}

// ===================================
// 19.7.3 类型函数（Type Functions）
// ===================================
类型函数是接受类型参数并返回新类型的模板。它们可以执行类型转换、组合或分解操作。
// 1.添加/移除引用
// 添加左值引用
template<typename T>
struct AddLValueReference {
    using Type = T&;
};

// 移除引用
template<typename T>
struct RemoveReference {
    using Type = T;
};

template<typename T>
struct RemoveReference<T&> {
    using Type = T;
};

template<typename T>
struct RemoveReference<T&&> {
    using Type = T;
};

// 2.添加/移除CV限定符
// 移除const
template<typename T>
struct RemoveConst {
    using Type = T;
};

template<typename T>
struct RemoveConst<const T> {
    using Type = T;
};

// =============================
// 19.7.4 条件类型（Conditional Types）
// =============================
条件类型允许我们基于编译期条件选择不同的类型。

// 1.基本条件类型
template<bool COND, typename TrueType, typename FalseType>
struct Conditional {
    using Type = TrueType;
};

// 偏特化 COND
template<typename TrueType, typename FalseType>
struct Conditional<false, TrueType, FalseType> {
    using Type = FalseType;
};

// 2.使用条件类型
// 根据类型大小选择适当的整数类型
template<std::size_t N>
struct IntType {
    using Type = typename Conditional<(N <= 8),
                                     uint8_t,
                                     typename Conditional<(N <= 16),
                                                         uint16_t,
                                                         uint32_t>::Type>::Type;
};


// =====================================
// 19.7.5 类型变换（Type Transformations）
// =====================================
类型变换特征允许我们系统地修改类型。

// 1.数组到指针的转换
template<typename T>
struct DecayArray {
    using Type = T;
};

template<typename T, std::size_t N>
struct DecayArray<T[N]> {
    using Type = T*;
};

// 2.函数到函数指针的转换
template<typename T>
struct DecayFunction {
    using Type = T;
};

template<typename R, typename... Args>
struct DecayFunction<R(Args...)> {
    using Type = R(*)(Args...);
};


// ===========================================
// 19.7.6 检测表达式有效性（Expression Validity）
// ===========================================
除了检测成员外，我们还可以检测任意表达式的有效性。

// 检测类型是否可比较
template<typename T, typename = void>
struct IsEqualityComparable : std::false_type {};

template<typename T>
struct IsEqualityComparable<T,
    std::void_t<decltype(std::declval<T>() == std::declval<T>())>> 
    : std::true_type {};

// ===========================================
// 19.7.7 SFINAE友好的特征（SFINAE-Friendly Traits）
// ===========================================
设计特征时，应确保它们在SFINAE上下文中表现良好，不会产生硬错误。

// 不友好的版本 - 可能导致硬错误
template<typename T>
struct BadTrait {
    static constexpr bool value = sizeof(T::nonexistent) > 0;  // 硬错误！
};

// 友好的版本 - 使用SFINAE
template<typename T, typename = void>
struct GoodTrait : std::false_type {};

template<typename T>
struct GoodTrait<T, std::void_t<decltype(T::nonexistent)>> : std::true_type {};

// ====================================
// 19.7.8 特征组合（Trait Composition）
// ====================================
通过组合基本特征，可以构建更复杂的特征。

// 检查类型是否为算术类型或枚举类型
template<typename T>
struct IsArithmeticOrEnum {
    static constexpr bool value = 
        std::is_arithmetic<T>::value || std::is_enum<T>::value;
};

// C++17中可以使用逻辑操作符
template<typename T>
inline constexpr bool is_arithmetic_or_enum_v = 
    std::is_arithmetic_v<T> || std::is_enum_v<T>;